package ${domain}.module.wsys.mgr;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import ${domain}.frame.base.ErrorType;
import ${domain}.frame.base.SortType;
import ${domain}.frame.auth.Token;
import ${domain}.frame.utils.IDgenerator;
import ${domain}.frame.utils.MapperUtil;
import ${domain}.frame.utils.Message;
import ${domain}.frame.utils.StringUtil;
import ${domain}.frame.utils.ValidationUtil;
import ${domain}.module.wsys.ent.Dept;
import ${domain}.module.wsys.ent.DeptTree;
import ${domain}.module.wsys.mpr.DeptMapper;
import ${domain}.module.wsys.req.DeptCreateRequest;
import ${domain}.module.wsys.req.DeptDeleteRequest;
import ${domain}.module.wsys.req.DeptFindRequest;
import ${domain}.module.wsys.req.DeptTreeRequest;
import ${domain}.module.wsys.req.DeptUpdateRequest;
import ${domain}.module.wsys.rsp.DeptCreateResponse;
import ${domain}.module.wsys.rsp.DeptDeleteResponse;
import ${domain}.module.wsys.rsp.DeptFindResponse;
import ${domain}.module.wsys.rsp.DeptTreeResponse;
import ${domain}.module.wsys.rsp.DeptUpdateResponse;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * DEPT - 部门
 *
 * @author wangbing
 * @version 0.0.1
 * @since 2017-01-01
 */
@Transactional
@Service
public class DeptManagerImpl implements DeptManager {

    @Autowired
    private DeptMapper deptMapper;

    /**
     * 插入
     *
     * @param request 请求对象
     * @param token   令牌
     * @return 响应
     */
    public DeptCreateResponse create(DeptCreateRequest request, Token token) {
        DeptCreateResponse response = new DeptCreateResponse();

        ValidationUtil.validate(request, response);
        if (response.hasError()) {
            return response;
        }

        //检查是否重复
        {
            DeptFindRequest deptFindRequest = new DeptFindRequest();
            deptFindRequest.setDeptCode(request.getDeptCode());
            DeptFindResponse deptFindResponse = this.find(deptFindRequest, token);
            if (deptFindResponse.getResult().size() > 0) {
                response.addError(ErrorType.BUSINESS_ERROR, "[" + request.getDeptCode() + "]机构代码重复");
                return response;
            }
        }

        long id = IDgenerator.nextId();
        Dept entity = MapperUtil.map(request, Dept.class);
        entity.setId(id);
        if (StringUtil.isEmpty(entity.getSupCode()) || StringUtil.isEmpty(entity.getSupName())) {
            String deptCode = entity.getDeptCode();
            while (deptCode.length() > 0) {
                deptCode = deptCode.substring(0, deptCode.length() - 1);
                DeptFindRequest deptFindRequest = new DeptFindRequest();
                deptFindRequest.setDeptCode(deptCode);
                DeptFindResponse deptFindResponse = this.find(deptFindRequest, token);
                if (deptFindResponse.getResult().size() > 0) {
                    Dept supDept = deptFindResponse.getResult().get(0);
                    entity.setSupCode(supDept.getDeptCode());
                    entity.setSupName(supDept.getDeptName());
                    break;
                }
            }
        }

        long result = deptMapper.insert(entity, token);
        if (1L != result) {
            response.addError(ErrorType.BUSINESS_ERROR, Message.CREATE_FAILURE);
            return response;
        }
        response.setId(id);

        return response;
    }

    /**
     * 逻辑删除
     *
     * @param request 请求对象
     * @param token   令牌
     * @return 响应
     */
    public DeptDeleteResponse delete(DeptDeleteRequest request, Token token) {
        DeptDeleteResponse response = new DeptDeleteResponse();

        ValidationUtil.validate(request, response);
        if (response.hasError()) {
            return response;
        }

        long result = deptMapper.delete(request.getId(), token);
        if (1L != result) {
            response.addError(ErrorType.BUSINESS_ERROR, Message.DELETE_FAILURE);
            return response;
        }
        response.setResult(result);

        return response;
    }

    /**
     * 更新
     *
     * @param request 请求对象
     * @param token   令牌
     * @return 响应
     */
    public DeptUpdateResponse update(DeptUpdateRequest request, Token token) {
        DeptUpdateResponse response = new DeptUpdateResponse();

        ValidationUtil.validate(request, response);
        if (response.hasError()) {
            return response;
        }

        Dept entity = deptMapper.getById(request.getId(), token);
        if (entity == null) {
            response.addError(ErrorType.BUSINESS_ERROR, Message.GET_FAILURE);
            return response;
        }

        MapperUtil.map(request, entity);
        long result = deptMapper.update(entity, token);
        if (1L != result) {
            response.addError(ErrorType.BUSINESS_ERROR, Message.UPDATE_FAILURE);
            return response;
        }
        response.setResult(result);

        return response;
    }

    /**
     * 查询
     *
     * @param request 请求对象
     * @param token   令牌
     * @return 响应
     */
    @Transactional(readOnly = true)
    public DeptFindResponse find(DeptFindRequest request, Token token) {
        DeptFindResponse response = new DeptFindResponse();

        ValidationUtil.validate(request, response);
        if (response.hasError()) {
            return response;
        }

        if (request.getPageSize() != 0) {
            PageHelper.startPage(request.getPageNumber(), request.getPageSize());
        }
        if (StringUtil.isNotEmpty(request.getSortKey())) {
            PageHelper.orderBy(request.getSortKey() + " " + request.getSortType());
        }
        PageInfo<Dept> pageInfo = new PageInfo<>(deptMapper.find(request, token));

        response.setResult(pageInfo.getList());
        response.setTotalCount(pageInfo.getTotal());

        return response;
    }

    @Override
    public DeptTreeResponse tree(DeptTreeRequest request, Token token) {
        DeptTreeResponse response = new DeptTreeResponse();

        ValidationUtil.validate(request, response);
        if (response.hasError()) {
            return response;
        }

        DeptFindRequest deptFindRequest = new DeptFindRequest();
        deptFindRequest.setPageSize(0);
        deptFindRequest.setValid(true);
        deptFindRequest.setSortKey("DEPT_CODE");
        deptFindRequest.setSortType(SortType.ASC);
        DeptFindResponse deptFindResponse = this.find(deptFindRequest, token);

        if (deptFindResponse.hasError()) {
            response.addErrors(deptFindResponse.getErrors());
            return response;
        }

        List<DeptTree> data = new ArrayList<>();
        Map<String, DeptTree> allMap = new HashMap<>();
        List<Dept> result = deptFindResponse.getResult();
        while (result.size() > 0) {
            Iterator<Dept> iterator = result.iterator();
            while (iterator.hasNext()) {
                Dept next = iterator.next();
                DeptTree tree = new DeptTree();
                tree.setId(next.getId());
                tree.setDeptCode(next.getDeptCode());
                tree.setDeptName(next.getDeptName());
                tree.setDeptAlias(next.getDeptAlias());
                tree.setValid(next.getValid());
                tree.setRowVersion(next.getRowVersion());

                tree.setValue(next.getDeptCode());
                tree.setLabel(next.getDeptName());

                allMap.put(tree.getValue(), tree);
                iterator.remove();
                //尝试获取上级资源
                String code = next.getDeptCode();
                DeptTree Ptree = null;
                while (code.length() > 0) {
                    code = code.substring(0, code.length() - 1);
                    Ptree = allMap.get(code);
                    if (Ptree != null) break;
                }
                if (Ptree != null) {
                    Ptree.addChild(tree);
                } else {
                    data.add(tree);
                }
            }
        }

        response.setResult(data);
        return response;
    }
}
